package spynx.desl.runtime.operators.impl;

import java.lang.reflect.Field;

import spynx.desl.Expression;
import spynx.desl.runtime.IExecutionContext;
import spynx.desl.runtime.IOperator;
import spynx.desl.runtime.IRuntimeEntity;
import spynx.desl.runtime.impl.FieldDataStorage;
import spynx.desl.runtime.impl.Invocator;

public class DotResolutionOperator implements IOperator {

	@Override
	public String getOperator() {
		return ".";
	}

	@Override
	public Object apply(IExecutionContext context, String operator, Object... args) {
		String memberName = args[1] instanceof Expression ? ((Expression) args[1]).getOperator() 
				: args[1].toString();
		Object obj = args[0];
		
		obj = context.resolveReference(obj);
		if (obj instanceof IRuntimeEntity) {
			Object res = ((IRuntimeEntity) obj).applyOperator(context, operator, memberName);
			if (res != null)
				return res;
		}
		
		obj = context.resolveValue(obj);
		
		if (obj == null)
			if (args[0] instanceof Expression)
				throw new NullPointerException(((Expression) args[0]).getOperator() + " is null"); 
			else 
				throw new NullPointerException();
		try {
			if (obj instanceof IRuntimeEntity) {
				Object res = ((IRuntimeEntity) obj).applyOperator(context, operator, memberName);
				if (res != null)
					return res;
			}
			
			Field field = obj.getClass().getField(memberName);
			return new FieldDataStorage(obj, field);
		} catch (Exception e) {
		} 
		
		//if (!DeslRuntimeUtil.hasMethod))
		
		return  new Invocator(obj, memberName);  
	}

}
